//-------------------------------------------------------------------------------------------------
// Universal KS0108 driver library
// (c) Rados�aw Kwiecie�, radek@dxp.pl
//-------------------------------------------------------------------------------------------------
#include "HD61202.h"
#include "font.h"
//-------------------------------------------------------------------------------------------------
#include "glcd.h"
#include "string.h"
#include "util.h"
//-------------------------------------------------------------------------------------------------
unsigned char screen_x = 0, screen_y = 0;
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_Initialize(void)
{
	unsigned char i;
	GLCD_InitializePorts();
	for(i = 0; i < 2; i++)
		GLCD_WriteCommand((DISPLAY_ON_CMD | ON), i);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_Shutdown(void){
	unsigned char i;
	GLCD_InitializePorts();
	for(i = 0; i < 2; i++)
		GLCD_WriteCommand((DISPLAY_ON_CMD | OFF), i);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_GoTo(unsigned char x, unsigned char y)
{
unsigned char i;
screen_x = x;
screen_y = y;

for(i = 0; i < HD61202_SCREEN_WIDTH/64; i++)
  {
  GLCD_WriteCommand(DISPLAY_SET_Y | 0,i);
  GLCD_WriteCommand(DISPLAY_SET_X | y,i);
  GLCD_WriteCommand(DISPLAY_START_LINE | 0,i);
  }
GLCD_WriteCommand(DISPLAY_SET_Y | (x % 64), (x / 64));
GLCD_WriteCommand(DISPLAY_SET_X | y, (x / 64));
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_ClearScreen(void)
{
unsigned char i, j;
for(j = 0; j < HD61202_SCREEN_HEIGHT/8; j++)
  {
  GLCD_GoTo(0,j);
  for(i = 0; i < HD61202_SCREEN_WIDTH; i++)
    GLCD_WriteData(0x00);
  }
  GLCD_GoTo(0,0);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_FillScreen(void)
{
unsigned char i, j;
for(j = 0; j < HD61202_SCREEN_HEIGHT/8; j++)
  {
  GLCD_GoTo(0,j);
  for(i = 0; i < HD61202_SCREEN_WIDTH; i++)
    GLCD_WriteData(0xff);
  }
  GLCD_GoTo(0,0);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteChar(char charToWrite)
{
char i, array[5];
charToWrite -= 32;
memcpypgm2ram(array, (rom char*)((unsigned int)font5x8_table+(5 * (int)charToWrite)), 5);
for(i = 0; i < 5; i++){
	GLCD_WriteData(array[i]);
}
GLCD_WriteData(0x00);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteString(char * stringToWrite)
{
while(*stringToWrite)
  GLCD_WriteChar(*stringToWrite++);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_WriteStringROM(rom char * stringToWrite)
{
	char tmpChar;
	while(*stringToWrite){
		memcpypgm2ram(&tmpChar, stringToWrite++, 1);
		GLCD_WriteChar(tmpChar);
	}
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
void GLCD_SetPixel(unsigned char x, unsigned char y, unsigned char color)
{
unsigned char tmp;
GLCD_GoTo(x, (y / 8));
GLCD_ReadData(); // dummy read?
GLCD_GoTo(x, (y / 8));
tmp = GLCD_ReadData();
GLCD_GoTo(x, (y / 8));

tmp |= (1 << (y % 8));
GLCD_WriteData(tmp);
}
//-------------------------------------------------------------------------------------------------
// this routine only works for bitmaps with height divisible by 8
// y is valid from 0 to 5, not 0 to 47
// dy is valid from 0 to 47
//-------------------------------------------------------------------------------------------------
void GLCD_Bitmap(char * bmp, unsigned char x, unsigned char y, unsigned char dx, unsigned char dy)
{
unsigned char i, j;
for(j = 0; j < dy / 8; j++)
  {
  GLCD_GoTo(x,y + j);
  for(i = 0; i < dx; i++) 
    GLCD_WriteData(*bmp++);
  }
  GLCD_GoTo(0,0);
}
//-------------------------------------------------------------------------------------------------
// this routine only works for bitmaps with height divisible by 8
// y is valid from 0 to 5, not 0 to 47
// dy is valid from 0 to 47
//-------------------------------------------------------------------------------------------------
void GLCD_BitmapROM(rom char * bmp, unsigned char x, unsigned char y, unsigned char dx, unsigned char dy)
{
unsigned char i, j;
for(j = 0; j < dy / 8; j++)
  {
  GLCD_GoTo(x,y + j);
  for(i = 0; i < dx; i++) 
    GLCD_WriteData(GLCD_ReadByteFromROMMemory(bmp++));
  }
  GLCD_GoTo(0,0);
}
//-------------------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
// this routine works for all bitmaps
// y is valid from 0 to 47
//-------------------------------------------------------------------------------------------------
/*
void GLCD_Blit(char * bmp, unsigned char x, unsigned char y, unsigned char dx, unsigned char dy)
{
	unsigned char i, j, bi, py = 8 - y % 8, tmpChar,
		buffer[8];

// todo: determine best approach with least number of GoTos
// (rtfm)
	if(x >= HD61202_SCREEN_WIDTH || y >= HD61202_SCREEN_HEIGHT || !dx || !dy)
		return;
	dx = min(HD61202_SCREEN_WIDTH-x, dx);
	dy = min(HD61202_SCREEN_HEIGHT-y, dy);
	
	if(py){	// offset row
		if(dy < py) // if total height is < height of first partial 8-row
			return;
// 2-3 sections:
//	top segment: 1-7 pixels high
//	middle rows: 8 pixels high each
//	bottom row: 1-7 pixels high, or part of middle rows
//
		for(j = y; j < y+dy; j+=8){
			for(bi = x; bi < x+dx; bi+=8){ // 8 columns at a time per row
				GLCD_GoTo(bi, (j / 8));
				GLCD_ReadData(); // dummy read
				for(i = bi; i < min(x+dx,bi+8); i++)
					buffer[i-bi] = GLCD_ReadData() & (0xff >> py);
				GLCD_GoTo(bi, (j / 8));
				for(i = bi; i < min(x+dx,bi+8); i++){
					// lsb on top
					tmpChar = buffer[i-bi] | bmp[i] << 8 - py;
					if()
					GLCD_WriteData(tmpChar);
				}	
			}	
		}	
	}else{		// standard row
	}

for(j = 0; j < dy / 8; j++)
  {
  GLCD_GoTo(x,y + j);
  for(i = 0; i < dx; i++) 
    GLCD_WriteData(*bmp++);
  }
  GLCD_GoTo(0,0);
}
*/